home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 3: CDPD 3
/
Almathera Ten on Ten - Disc 3: CDPD3.iso
/
fish
/
726-750
/
744
/
autorunner
/
autorunner.p
< prev
next >
Wrap
Text File
|
1995-03-18
|
12KB
|
308 lines
{AutoRunner is the creation of Jon Maxwell. It can be freely distributed,
following the rules written in the main documentation}
PROGRAM AutoRunner (Input,output);
{Includes for PCQ Pascal, by Patrick Quaid}
{$I "Include:Intuition/Intuition.i"}
{$I "Include:Exec/Ports.i"}
{$I "Include:Exec/Lists.i"}
{$I "Include:Libraries/DOS.i"}
{$I "Include:Utils/StringLib.i"} {Includes for PCQ Pascal, by Patrick Quaid}
{$I "Include:Utils/DOSUtils.i"}
{$I "Include:Exec/Devices.i"}
{$I "Include:Exec/IO.i"}
{$I "Include:Exec/Tasks.i"}
{$I "Include:Devices/Trackdisk.i"}
CONST
{Gadgets, obviously}
Gad5:Gadget=( nil,25,0,180,10,GADGHNONE,0,WDRAGGING,nil,nil,nil,0,nil,-1,nil);
Gad4Text:IntuiText=(1,0,JAM1,0,1,nil,"3",nil);
Gad4:Gadget=( nil,230,0,10,10,GADGHCOMP,GADGIMMEDIATE,BOOLGADGET,nil,nil,@Gad4Text,0,nil,3,nil);
Gad3Text:IntuiText=(1,0,JAM1,0,1,nil,"2",nil);
Gad3:Gadget=(@Gad4,220,0,10,10,GADGHCOMP,GADGIMMEDIATE,BOOLGADGET,nil,nil,@Gad3Text,0,nil,2,nil);
Gad2Text:IntuiText=(1,0,JAM1,0,1,nil,"1",nil);
Gad2:Gadget=(@Gad3,210,0,10,10,GADGHCOMP,GADGIMMEDIATE,BOOLGADGET,nil,nil,@Gad2Text,0,nil,1,nil);
Gad1Text:IntuiText=(1,0,JAM1,0,1,nil,"0",nil);
Gad1:Gadget=(@Gad2,200,0,10,10,GADGHCOMP,GADGIMMEDIATE,BOOLGADGET,nil,nil,@Gad1Text,0,nil,0,nil);
VAR
TempAddr:Address;
I:boolean;
Loop:Integer;
Wind:WindowPtr;
DiskValue:Array [0..3] OF Integer; {Stores Old Disk ID so they won't be researched automatically}
CONST
Unit2Check:Array [0..3] OF Boolean=(TRUE,TRUE,FALSE,FALSE); {Which drives should be checked, default}
OnlyOnce:Boolean=FALSE; {Check startup drives and then quit if True}
CDFlag:Boolean=TRUE; {CD to inserted disk?}
StartCheck:Boolean=TRUE;{Check drives on startup?}
MaxUnit=3; {Largest unit number}
StdInName : String = "CON:0/0/1/1/AutoRunnerCLI"; {1 Pixel CLI if no input/output}
StdOutName : String = StdInName;
AwakeStr="Auto Runner: Awake ";
Sleeping="Auto Runner: Sleeping ";
UnitNames:Array [0..3] Of String=("DF0:","DF1:","DF2:","DF3:");
{----------------------}
PROCEDURE MakeUnit2CheckList;
VAR {reads passed param for units and flags}
Num,
Loop:Integer;
BEGIN
FOR Loop:=0 TO 3 DO Unit2Check[Loop]:=FALSE;
FOR Loop:=0 TO strlen(CommandLine) DO BEGIN
CommandLine[Loop]:=ToUpper(CommandLine[Loop]);
Num:=ord(CommandLine[Loop])-ord('0');
IF (Num>-1) AND (Num<(MaxUnit+1)) THEN Unit2Check[Num]:=TRUE;
IF CommandLine[Loop]='C' THEN CDFlag:=FALSE;
IF CommandLine[Loop]='S' THEN StartCheck:=FALSE;
IF CommandLine[Loop]='O' THEN OnlyOnce:=TRUE;
END;
END;
{----------------------}
PROCEDURE OpenTheWindow;
{Old OpenTheWindow used WITH .. BEGIN to assign values to a NwPtr, but
that meant that the info must be in the program code anyway! This way,
using a Constant, it saves program space (around 260 bytes) and saves
time because everything is setup at compilation! }
CONST
Nw:NewWindow=(0,10,300,10,1,0,MENUPICK_f+CLOSEWINDOW_f+GADGETDOWN_f+DISKINSERTED_f+ACTIVEWINDOW_f,WINDOWDEPTH+WINDOWCLOSE,nil,nil,AwakeStr,nil,nil,1,1,1023,1023,WBENCHSCREEN_f);
BEGIN
Wind:=OpenWindow(@Nw);
IF Wind=nil THEN Exit(0);
END;
{----------------------}
PROCEDURE LoadMenu (DriveNum:integer); {Loads and execute()'s the comments}
VAR
I:Integer;
FL:FileLock;
OldDir:FileLock; {In case you have CDFlag set, this stores the startup-dir}
FIB:FileInfoBlockPtr;
TempChar:Char;
NotDirEnd:Boolean; {Last item in the dir?}
OldCDFlag:Boolean; {Just stores default CD flag setting temporarily}
TYPE
CommentBlock=RECORD {A Comment Block is New()ed when a comment is found--Dynamic allocation!}
NextBlock:^CommentBlock;
Comment:ARRAY [0..79] OF Char;
Flags:Integer;
END;
CommentPtr=^CommentBlock;
VAR
TempComment:CommentPtr; {These three keep track of the Comments found}
Base:CommentPtr;
CurComment:CommentPtr;
BEGIN
{This is a mess, but it works...}
{OUTLINE of this routine:
I. Get root dir file lock
II. Look through all the Comments
A. Examine()
B. Autorunner Comment?
1. Allocate New CommentBlock
2. Fill in Current CommentBlock^.Next
III. Execute() Comments!
}
Base:=nil;
new(FIB); NotDirEnd:=TRUE;
FL:=Lock(UnitNames[DriveNum],SHARED_LOCK);
IF FL=nil THEN BEGIN writeln("Can't get a (shared) lock on ",UnitNames[DriveNum],"!"); Return; END;
IF NOT Examine(FL,FIB) THEN BEGIN unlock(FL); Dispose(FIB); Return; END;
REPEAT
IF (FIB^.fib_Comment[0]='¿') OR (FIB^.fib_Comment[0]='¡') THEN BEGIN
TempComment:=CurComment;
new(CurComment); IF Base=nil THEN Base:=CurComment;
TempComment^.NextBlock:=CurComment;
writeln(String(adr(FIB^.fib_Comment[1])));
FOR I:=0 TO 79 DO CurComment^.Comment[I]:=FIB^.fib_Comment[I];
END;
NotDirEnd:=ExNext(FL,FIB);
UNTIL NotDirEnd=FALSE;
CurComment:=Base;
IF CurComment<>nil THEN
REPEAT
OldCDFlag:=CDFlag;
IF CurComment^.Comment[0]='¡' THEN BEGIN
IF CurComment^.Comment[1]='C' THEN CDFlag:=TRUE;
IF CurComment^.Comment[1]='c' THEN CDFlag:=FALSE;
END;
IF CDFlag THEN OldDir:=CurrentDir(FL);
IF CurComment^.Comment[0]='¿' THEN IF Execute(String(@CurComment^.Comment[1]),FileHandle(nil),GetFileHandle(Output)) THEN;
IF CurComment^.Comment[0]='¡' THEN IF Execute(String(@CurComment^.Comment[2]),FileHandle(nil),GetFileHandle(Output)) THEN;
IF CDFlag=TRUE THEN FL:=CurrentDir(OldDir);
CDFlag:=OldCDFlag;
TempComment:=CurComment;
CurComment:=CurComment^.NextBlock;
dispose(TempComment);
UNTIL CurComment=nil;
CurComment:=nil; {PCQ Pascal will still try to Dispose() sometimes -> Guru}
UnLock(FL);
Dispose(FIB);
END;
{----------------------}
FUNCTION DiskInDrive (UnitNum:Integer):Boolean;
VAR
io:IOStdReqPtr;
MPort:MsgPortPtr; {for when trackdisk is done with the IO}
Error:Integer;
BEGIN
new(io);
new(MPort);
newlist(adr(MPort^.mp_MsgList));
MPort^.mp_Flags:=PASignal; { \ }
MPort^.mp_SigTask:=FindTask(nil); { =Sets up Message port}
MPort^.mp_SigBit:=1; { / }
io^.io_Message.mn_ReplyPort:=MPort; { \sets up IO_messsage}
io^.io_Message.mn_Length:=sizeof(IOStdReq); { /structure with stuff}
{Error is a placeholder after the opendevice check, becuase I don't test for errors after!}
Error:=OpenDevice("trackdisk.device",UnitNum,io,0);
IF Error<>0 THEN BEGIN writeln("Can't open unit: ",UnitNum); DiskInDrive:=FALSE; END;
io^.io_Command:=TD_CHANGESTATE;
Error:=DoIO(io);
Error:=WaitIO(io); {DoIO should wait, but perhaps it might mess up... :) }
Error:=io^.io_Actual; {Error now tells whether a disk is in the unit}
CloseDevice(io);
dispose(io); { \releases memory-> less likely}
dispose(MPort); { /to fragment memory}
IF Error=0 THEN DiskInDrive:=TRUE;
DiskInDrive:=FALSE;
END;
{----------------------}
FUNCTION VNode(FL:FileLock):integer;
{Returns an ID for the disk}
{ (I know that there is something in the system to do this reliably,}
{ but I don't know how to find it yet) }
{PROBLEM: Simply takes the hash of the first two filenames -- I couldn't
figure out how to get the Disk ID, whereever or whatever that is, but
this works well enough... The Disk ID doesn't play a vital role anyway}
VAR
VolNode:integer;
ID:InfoDataPtr;
FIB:FileInfoBlockPtr;
BEGIN
new(ID);
new(FIB);
IF Examine(FL,FIB) THEN BEGIN
VolNode:=hash(string(adr(FIB^.fib_FileName[0])));
IF ExNext(FL,FIB) THEN VolNode:=VolNode+hash(string(adr(FIB^.fib_FileName[0])));
VNode:=VolNode;
END
ELSE
VNode:=0;
dispose(ID);
dispose(FIB);
END;
{----------------------}
FUNCTION FindDiskInserted:Integer;
{uses Disk IDs for the disks to find out which drive a disk was inserted in}
VAR
FLock:FileLock;
Loop:Integer;
BEGIN
FOR Loop:=0 TO MaxUnit DO
BEGIN
IF (Unit2Check[Loop]=TRUE) AND (DiskInDrive(Loop)) THEN BEGIN
FLock:=Lock(UnitNames[Loop],Access_Read);
IF FLock=nil THEN BEGIN Writeln("Bad Lock!"); FindDiskInserted:=-1; END;
IF (VNode(FLock)<>DiskValue[Loop]) THEN {Makes sure disk isn't last one that was in the unit}
BEGIN
DiskValue[Loop]:=VNode(FLock);
UnLock(FLock);
FindDiskInserted:=Loop;
END;
UnLock(FLock);
END;
END;
FindDiskInserted:=-1; {-1 cancels further action}
END;
{----------------------}
PROCEDURE GetDoMsg;
{Monitors window IDCMP port for gadget & diskinserted messages, and calls
appropriate routines}
VAR
Code,
Qualifier:Short;
MsgClass:Integer;
IM:IntuiMessagePtr;
Gad:GadgetPtr;
BEGIN
WHILE 2=2 DO BEGIN
IM:=IntuiMessagePtr(WaitPort(Wind^.UserPort));
IM:=IntuiMessagePtr(GetMsg (Wind^.UserPort));
MsgClass:=IM^.Class;
Code:=IM^.Code;
Qualifier:=IM^.Qualifier;
Gad:=GadgetPtr(IM^.IAddress);
ReplyMsg(MessagePtr(IM));
IF (MsgClass=GADGETDOWN_f) OR (MsgClass=GADGETUP_f) THEN BEGIN
IF DiskInDrive(Gad^.GadgetID) THEN LoadMenu(Gad^.GadgetID);
END;
IF (MsgClass=ACTIVEWINDOW_f) THEN
RefreshGadgets(@Gad1,Wind,nil);
IF MsgClass=DISKINSERTED_f THEN BEGIN
Code:=FindDiskInserted;
IF Code>-1 THEN LoadMenu(Code);
END;
IF MsgClass=MENUPICK_f THEN BEGIN
SetWindowTitles(Wind,Sleeping,Sleeping);
RefreshGadgets(@Gad1,Wind,nil);
REPEAT
IM:=IntuiMessagePtr(WaitPort(Wind^.UserPort));
IM:=IntuiMessagePtr(GetMsg(Wind^.UserPort));
MsgClass:=IM^.Class;
ReplyMsg(MessagePtr(IM));
UNTIL MsgClass=MENUPICK_f;
SetWindowTitles(Wind,AwakeStr,AwakeStr);
RefreshGadgets(@Gad1,Wind,nil);
END;
IF MsgClass=CLOSEWINDOW_f THEN BEGIN
CloseWindow(Wind);
Exit(0);
END;
END;
END;
{----------------------}
BEGIN
Unit2Check[0]:=TRUE; { \ }
Unit2Check[1]:=TRUE; { \ default drives }
Unit2Check[2]:=FALSE; { /to be checked & }
Unit2Check[3]:=FALSE; { /not to be checked }
IF strlen(CommandLine)>1 THEN {Checks for CLI Param}
IF CommandLine[0]='?' THEN BEGIN {TRUE=Print Below Info}
writeln("AutoRunner is copyright (©) 1991 by Jonathan Maxwell");
writeln("----------------------------------------------------");
writeln("USAGE: AutoRunner ####sco, Where #### are the units ");
writeln(" to check and sco are the flags, in any order.");
writeln("FLAGS: S=doesn't check drives when started");
writeln(" C=doesn't auto-cd to inserted disk");
writeln(" O=checks drives when started and then");
writeln(" quits immediately");
writeln("COMMENT SYNTAX:");
writeln(" ¿command OR ¡<flag>command");
writeln(" ¿=SHIFT ALT m (or ALT M)");
writeln(" ¡=ALT i");
writeln(" <flag>=C for forced CD (overrides command line)");
writeln(" <flag>=c for forced NO-CD mode");
Exit(0);
END
{FALSE=get units to check and flags}
ELSE MakeUnit2CheckList;
IF OnlyOnce=FALSE THEN BEGIN
OpenTheWindow;
ClearMenuStrip(Wind); {Does this do anything here? I think not...}
Loop:=AddGList(Wind,@Gad1,1,4,nil); {Add the 4 device re-check gadgets}
Loop:=AddGadget(Wind,@Gad5,1);
RefreshGadgets(@Gad1,Wind,nil);{Make the gadgets visable}
END;
IF StartCheck=TRUE THEN {Following checks all set units unless flag was turned off}
FOR Loop:=0 TO MaxUnit DO BEGIN
IF Unit2Check[Loop]=TRUE THEN BEGIN
I:=DiskInDrive(Loop); {Makes sure a disk is in the drive (avoids "No disk in unit #" message) }
IF I THEN LoadMenu(Loop);
END;
END;
IF OnlyOnce=FALSE THEN GetDoMsg; {Main Control Center}
END.